﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core;
using Cofe.Core.Filter;
using Cofe.Core.Implements;
using Cofe.Data.Utils.ThirdParty;

namespace Cofe.Data.Filter
{
    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFEDB)]
    public class PropertyEntryFilterExpression : 
        IEntryFilterExpression<PropertyEntryFilter>
    {
        public Expression<Func<CofeSystemInfo, bool>>
            GetQueryExpression(PropertyEntryFilter entryFilter, IOptionFilter[] options)
        {       
            Type propertyType = DecoratorExtension.GetDefaultType(entryFilter.Property);
            int op = entryFilter.Value.StartsWith(">") ? 1 : entryFilter.Value.StartsWith("<") ? -1 : 0;
            object value = entryFilter.Value.TrimStart('<', '>');
            MethodInfo mi = typeof(PropertyEntryFilterExpression).GetMethod("createExpression").MakeGenericMethod(propertyType);
            var exp = (Expression<Func<CofeSystemInfo, bool>>)mi.Invoke(this, new object[] { entryFilter.Property, op, value });           
          
            if (entryFilter.Negative)
                return exp.Not();
            return exp;
        }

        public Expression<Func<CofeSystemInfo, bool>> createExpression<T>(object property, int op, object value)
        {
            var propExpr = CofeServices.PropertyDictionary.GetPropertyExpression<T>(property);            
            T valueT = (T)Convert.ChangeType(value, typeof(T));
            Expression<Func<CofeSystemInfo, bool>> exp;
            switch (op)
            {
                case -1: exp = LambaUtils.LesserExpr(propExpr, valueT); break;
                case 1: exp = LambaUtils.GreaterOrEqualExpr(propExpr, valueT); break;
                default: exp = LambaUtils.EqualExpr(propExpr, valueT); break;
            }
            return exp;
        }
    }
}
